package com.rgs.base.database;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.rgs.base.database.sql.*;
import tk.mybatis.mapper.entity.Example;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Objects;

/**
 * @author Ren Gaoshuai
 * @ClassName SqlPlusUtil
 * @date 2021-12-24 10:33
 **/
public class SqlPlusUtil {
    private SqlPlusUtil() {

    }

    private static final String FULL_LIKE_STRING = "%{}%";
    private static final String AFTER_LIKE_STRING = "{}%";

    public static String fullLike(String para) {
        return StrUtil.format(FULL_LIKE_STRING, para);
    }

    public static String afterLike(String para) {
        return StrUtil.format(AFTER_LIKE_STRING, para);
    }


//    private static void notFilter(Example.Criteria criteria) {
//        criteria.andCondition("1=", "2");
//    }

    private static void sqlFilterJoinOne(Example.Criteria criteria,
                                         Object objValue, String columnName,
                                         LikeTypeEnum likeTypeEnum,
                                         SqlConditionEnum sqlConditionEnum) {

        switch (sqlConditionEnum) {
            case EQUAL:
                if (objValue instanceof Iterable) {
                    if (!CollectionUtil.isEmpty((Iterable) objValue)) {
                        criteria.andIn(columnName, (Iterable) objValue);
                    }
                } else if (objValue instanceof SqlFilterBetweenBO) {
                    SqlFilterBetweenBO sqlFilterBetweenTemp = (SqlFilterBetweenBO) objValue;
                    criteria.andBetween(columnName, sqlFilterBetweenTemp.getBegin(), sqlFilterBetweenTemp.getEnd());
                } else if (objValue instanceof String) {
                    if (!Strings.isNullOrEmpty((String) objValue)) {
                        switch (likeTypeEnum) {
                            case NONE:
                                criteria.andEqualTo(columnName, objValue);
                                break;
                            case AFTER:
                                criteria.andLike(columnName, afterLike((String) objValue));
                                break;
                            default:
                                criteria.andLike(columnName, fullLike((String) objValue));
                                break;
                        }
                    }

                } else {
                    criteria.andEqualTo(columnName, objValue);
                }
                break;
            case REGULAR:
                if (!Strings.isNullOrEmpty(objValue.toString())) {
                    //columnName = CaseFormatStaticClass.CAMEL_TO_UNDERSCORE.convert(columnName);
                    criteria.andCondition(columnName.concat(" REGEXP "), objValue.toString());
                }
                break;
            default:
                break;
        }

    }

    public static <T1, T2 extends ISqlFilter> Example sqlFilterJoin(Class<T1> oClass, T2 filter) {
        Example example = new Example(oClass);
        Example.Criteria criteria = example.createCriteria();
        //反射类获取所有public属性，包括父类
        Field[] fields = ReflectUtil.getFields(filter.getClass());
        for (Field fieldTemp : fields) {
            SqlFilterAnnotation annotation = fieldTemp.getAnnotation(SqlFilterAnnotation.class);
            if (Objects.isNull(annotation)) {
                continue;
            }
            fieldTemp.setAccessible(true);
            Object objValue = null;
            try {
                //获取该属性的类型
                objValue = fieldTemp.get(filter);
            } catch (IllegalAccessException exception) {
                //log.error(exception.getMessage());
                continue;
            }
            if (Objects.isNull(objValue)) {
                continue;
            }
            //
            String columnName;
            LikeTypeEnum likeTypeEnum;
            //动态条件判断，Integer类型
            if (annotation.customConditions().length > 0 && objValue instanceof Integer) {
                criteria.andCondition(annotation.customConditions()[(Integer) objValue]);
                continue;
            }
            if (annotation.dynamicFilterArray().length > 0) {
                Preconditions.checkNotNull(filter.getDynamicFilterIndex());
                Preconditions.checkElementIndex(filter.getDynamicFilterIndex(),
                        annotation.dynamicFilterArray().length);
                SqlFilterDynamicFilterAnnotation sqlFilterDynamicFilter
                        = annotation.dynamicFilterArray()[filter.getDynamicFilterIndex()];
                columnName = sqlFilterDynamicFilter.dynamicName();
                if (Strings.isNullOrEmpty(columnName)) {
                    continue;
                }
                likeTypeEnum = sqlFilterDynamicFilter.likeType();
            }
            else {
                columnName = annotation.columnName();
                likeTypeEnum = annotation.likeType();
            }
            sqlFilterJoinOne(criteria, objValue, columnName, likeTypeEnum,
                    annotation.sqlCondition());
        }
        if (CollUtil.isNotEmpty(filter.getVagueFilterColumn())) {
            Map<String, String> filterMap = filter.getVagueFilterColumn();
            for (Map.Entry<String, String> entry : filterMap.entrySet()) {
                if (Objects.isNull(entry.getValue()) || Objects.isNull(entry.getKey())) {
                    continue;
                }
                sqlFilterJoinOne(criteria, entry.getValue(), entry.getKey(),
                        LikeTypeEnum.FULL, SqlConditionEnum.EQUAL);
            }
        }
        if (!Strings.isNullOrEmpty(filter.getOrderByClause())) {
            example.setOrderByClause(filter.getOrderByClause());
        }
        return example;
    }

}

